#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<errno.h>
#include<signal.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<pthread.h>
#include<assert.h>

struct ServerData
{
    int PORT;
    char *AddressIP;
    struct sockaddr_in server;
    struct sockaddr_in clinet;
    int listen_fd;
    int server_fd;
}ServerDataStruct;

void signal_handler(int arg){
    // printf("close listen_fd(signal = %d)\n", arg);
    close(ServerDataStruct.listen_fd);
    exit(0);
}

void *read_fun(void *arg){
    int *read_fd=(int *)arg;
    char read_buf[100]={'\0'};
    while (1){
        if(recv(*read_fd,read_buf,100,0)<0){
            perror("recv failed");
            exit(-1);           
        }else{
            printf("%saccept data:%s\n",inet_ntoa(ServerDataStruct.clinet.sin_addr),read_buf);
        }
        memset(read_buf,'\0',100);
    }
}

void *write_fun(void *arg){
    int *write_fd=(int *)arg;
    char write_buf[100]={'\0'};
    while (1){
        printf("server input:\n");
        fgets(write_buf,100,stdin);
        if(send(*write_fd,write_buf,100,0)<0){
            perror("send failed");
            exit(-1);           
        }
        memset(write_buf,'\0',100);
    }
}

int main(int argc,char **argv){
    int new_fd=-1;
    void *optlen=NULL;
    char recv_buf[100]={'\0'};
    socklen_t saddrlen=sizeof(ServerDataStruct.server);
    socklen_t caddrlen=sizeof(ServerDataStruct.clinet);

    //当终端有ctrl+c时关闭监听套接字
    signal(SIGINT,signal_handler);

    //初始化服务端和客户端
    memset(&ServerDataStruct.server,0,sizeof(ServerDataStruct.server));
    memset(&ServerDataStruct.clinet,0,sizeof(ServerDataStruct.clinet));

    //创建服务器的套接字
    ServerDataStruct.server_fd=socket(AF_INET,SOCK_STREAM,0);
    if(ServerDataStruct.server_fd<0){
        perror("socket failed");
        return -1;
    }
    
    // //设置套接字选项，地址和端口可以复用
    // if(setsockopt(ServerDataStruct.server_fd,SOL_SOCKET,SO_REUSEADDR,optlen,sizeof(optlen))<0){
    //     perror("setsockopt failed");
    //     return -1;
    // }
    
    //获取ip地址和端口号
    ServerDataStruct.AddressIP=argv[1];
    ServerDataStruct.PORT=atoi(argv[2]);

    ServerDataStruct.server.sin_family=AF_INET;
    ServerDataStruct.server.sin_addr.s_addr=inet_addr(ServerDataStruct.AddressIP);//inet_addr(ServerDataStruct.AddressIP)
    ServerDataStruct.server.sin_port=htons(ServerDataStruct.PORT);

    //将套接字与IP地址和端口和绑定
    if(bind(ServerDataStruct.server_fd,(struct sockaddr*)(&ServerDataStruct.server),sizeof(struct sockaddr))<0){
        perror("bind failed");
        return -1;
    }

    //监听套接字，接收客户端的连接
    ServerDataStruct.listen_fd=listen(ServerDataStruct.server_fd,5);
    if(ServerDataStruct.listen_fd<0){
        perror("listen failed");
        return -1;
    }
    
    // int accept_size=sizeof(struct sockaddr);
    // new_fd=accept(ServerDataStruct.server_fd,(struct sockaddr*)(&ServerDataStruct.clinet),&accept_size);
    // if(new_fd<0){
    //     perror("accept failed");
    //     exit(-1);
    // }

    // while(1){
    //     if(recv(new_fd,recv_buf,80,0)<0){
    //         perror("recv failed");
    //         exit(-1);           
    //     }
        
    //     printf("%d:%s\n",ServerDataStruct.clinet.sin_addr.s_addr,recv_buf);
    // }

    while(1){
        int accept_size=sizeof(struct sockaddr);
        new_fd=accept(ServerDataStruct.server_fd,(struct sockaddr*)(&ServerDataStruct.clinet),&accept_size);
        if(new_fd<0){
            perror("accept failed");
            exit(-1);
        }else{
            int rres,wres;
            pthread_t Rid,Wid;
            rres=pthread_create(&Rid,NULL,read_fun,(void *)&new_fd);
            assert(rres == 0);
            wres=pthread_create(&Wid,NULL,write_fun,(void *)&new_fd);
            assert(wres == 0);
        }
    }
    
    close(ServerDataStruct.listen_fd);
    close(ServerDataStruct.server_fd);
    return 0;
}